home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp95
/
freyja.exe
/
lha
/
DISPLAY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-13
|
16KB
|
827 lines
/* DISPLAY.C -- Redisplay and Display Routines
Written March 1991 by Craig A. Finseth
Copyright 1991 by Craig A. Finseth
*/
#include "freyja.h"
#define WINMINHEIGHT 3
static char screen[ROWMAX][COLMAX + 1];
static int screen_line_used[ROWMAX + 1] = { 0 };
static int screen_line_len[ROWMAX + 1] = { 0 };
static int point_row;
static char mode_flags[8];
static FLAG need_screen_range;
static int divide;
static char mode_buf[COLMAX + 1];
static FLAG div_shown = FALSE;
#if defined(MSDOS)
static int jmenu_which = -1;
static int jmenu_cols[] = { 0, 6, 12, 18 };
#endif
void D_Clear(); /* int row */
void D_ClearScreen(); /* void */
void D_ClearWind(); /* struct window *wptr */
void D_IncrDisplay(); /* FLAG nested_call */
void D_IncrDisplay2(); /* FLAG nested_call */
void D_IncrDisplay3(); /* void */
int D_InnerDisplay(); /* struct window *wptr, struct mark *point */
void D_InnerDisplay2(); /* struct window *wptr; int row */
void D_ScreenRange(); /* FLAG nested_call */
/* ------------------------------------------------------------ */
/* Initialize the display routines, part 1. */
void
DInit1()
{
int cnt;
num_windows = 1; /* one window at the top */
divide = TMaxRow() - 1;
for (cnt = 0; cnt < NUMWINDOWS; cnt++) {
windows[cnt].visible = FALSE;
windows[cnt].sstart = NULL;
windows[cnt].send = NULL;
windows[cnt].point = NULL;
}
windows[0].visible = TRUE;
windows[0].top = 0;
windows[0].bot = TMaxRow() - 2;
windows[0].isend = FALSE;
windows[0].offset = 0;
cwin = &windows[0];
need_screen_range = TRUE;
}
/* ------------------------------------------------------------ */
/* Initialize the display routines, part 2. */
void
DInit2()
{
windows[0].sstart = BMarkCreate();
windows[0].send = BMarkCreate();
windows[0].point = BMarkCreate();
D_ClearScreen();
}
/* ------------------------------------------------------------ */
/* Terminate the display routines. */
void
DFini()
{
}
/* ------------------------------------------------------------ */
/* Display a message in the echo line. */
void
DEcho(msg)
char *msg;
{
TSetPoint(TMaxRow() - 1, 0);
THiOn();
strncpy(mode_buf, msg, TMaxCol() + 1);
mode_buf[TMaxCol()] = NUL;
TPutStr(mode_buf);
TCLEOL();
THiOff();
TForce();
}
/* ------------------------------------------------------------ */
/* Display a message in the echo line, but don't move the cursor. */
void
DEchoNM(msg)
char *msg;
{
int row;
int col;
row = TGetRow();
col = TGetCol();
DEcho(msg);
TSetPoint(row, col);
TForce();
}
/* ------------------------------------------------------------ */
/* Display an error message */
void
DError(msg)
char *msg;
{
char buf[2 * COLMAX + 1];
int row;
int col;
row = TGetRow();
col = TGetCol();
xsprintf(buf, ">>> %s", msg);
DEcho(buf);
TBell();
KGetChar();
DModeLine();
TSetPoint(row, col);
TForce();
}
/* ------------------------------------------------------------ */
/* Update the display from the buffer */
void
DIncrDisplay()
{
int cnt;
if (need_screen_range) {
D_ScreenRange(FALSE);
DModeLine();
}
if (num_windows > 1) {
if (!div_shown) {
div_shown = TRUE;
TSetPoint(divide, 0);
THiOn();
for (cnt = 0; cnt < TMaxCol(); ++cnt)
TPutChar('-');
THiOff();
}
}
else div_shown = FALSE;
D_IncrDisplay(FALSE);
}
/* ------------------------------------------------------------ */
/* Put up the menu for the Jaguar version. */
#if defined(MSDOS)
void
DJMenus(which)
int which;
{
int cnt;
D_Clear(0);
D_Clear(1);
D_Clear(2);
#if !defined(SYSMGR)
jmenu_which = which;
if (jmenu_which < 0) return;
TSetPoint(0, 0);
TPutStr("Help Open Save Quit");
TCLEOL();
TSetPoint(1, 0);
TCLEOL();
#endif
TSetPoint(2, 0);
for (cnt = 0; cnt < TMaxCol(); ++cnt) TPutChar('\xcd');
TSetPoint(0, jmenu_cols[which]);
}
#endif
/* ------------------------------------------------------------ */
/* Scroll the window left. */
void
DLeft()
{
if (!isuarg) uarg = BGetCol() - (TMaxCol() - HOVERLAP);
if (uarg < 0) uarg = 0;
BMakeColF(uarg);
uarg = 0;
D_ClearWind(cwin);
}
/* ------------------------------------------------------------ */
/* Display the mode flags */
void
DModeFlags()
{
long loc;
long len;
int pct;
char buf[LINEBUFFSIZE];
if (KIsKey() == 'Y') return;
loc = BGetLocation();
len = BGetLength(cbuf);
if (len == 0) len = 1;
pct = (loc * 100) / len;
xsprintf(buf, "%3d%% %c%c",
pct,
BIsMod(cbuf) ? '*' : ' ',
TabIsDelete(lastkey, lasttable) ? '+' : ' ');
if (!strequ(mode_flags, buf)) {
TSetPoint(TMaxRow() - 1, 12);
THiOn();
TPutStr(buf);
THiOff();
xstrcpy(mode_flags, buf);
}
}
/* ------------------------------------------------------------ */
/* Display the mode line */
void
DModeLine()
{
char buf[2 * COLMAX + 1];
TSetPoint(TMaxRow() - 1, 0);
xsprintf(buf, "Freyja V1.4 ###%% *+ %s", cbuf->fname);
TCLEOL();
*mode_flags = NUL;
DEcho(buf);
DModeFlags();
}
/* ------------------------------------------------------------ */
/* Put a new display on the screen. */
void
DNewDisplay()
{
TClrScreen();
D_ClearScreen();
D_ScreenRange(FALSE);
div_shown = FALSE;
DModeLine();
}
/* ------------------------------------------------------------ */
/* Return the current preferred line. */
int
DPrefLine()
{
return((PREF_PCT * DWindHeight()) / 100);
}
/* ------------------------------------------------------------ */
/* Scroll the window right. */
void
DRight()
{
if (!isuarg) uarg = BGetCol() + (TMaxCol() - HOVERLAP);
if (uarg < 0) uarg = 0;
BMakeColF(uarg);
uarg = 0;
D_ClearWind(cwin);
}
/* ------------------------------------------------------------ */
/* Center redisplay */
void
DScreenRange()
{
need_screen_range = TRUE;
}
/* ------------------------------------------------------------ */
/* Toggle the visible gray flag. */
void
DTogVisGray()
{
c.g.vis_gray = !c.g.vis_gray;
DNewDisplay();
}
/* ------------------------------------------------------------ */
/* Display an informative message in the message area and wait for a
key press. */
void
DView(msg)
char *msg;
{
int row;
int col;
row = TGetRow();
col = TGetCol();
DEcho(msg);
KGetChar();
DModeLine();
TSetPoint(row, col);
TForce();
}
/* ------------------------------------------------------------ */
/* Grow the current window. */
void
DWindGrow()
{
int height;
int cnt;
if (num_windows <= 1) return;
D_Clear(divide);
if (cwin > &windows[0]) { /* move divider up */
height = (cwin - 1)->bot - (cwin - 1)->top + 1;
if (uarg > height - WINMINHEIGHT) uarg = height - WINMINHEIGHT;
if (uarg >= 1) {
for (cnt = (cwin - 1)->bot - uarg + 1;
cnt < (cwin - 1)->bot; cnt++) {
D_Clear(cnt);
}
divide -= uarg;
(cwin - 1)->bot -= uarg;
cwin->top -= uarg;
}
}
else { /* move divider down */
height = (cwin + 1)->bot - (cwin + 1)->top + 1;
if (uarg > height - WINMINHEIGHT) uarg = height - WINMINHEIGHT;
if (uarg >= 1) {
for (cnt = (cwin + 1)->top;
cnt < (cwin + 1)->top + uarg - 1; cnt++) {
D_Clear(cnt);
}
divide += uarg;
cwin->bot += uarg;
(cwin + 1)->top += uarg;
}
}
div_shown = FALSE;
DModeLine();
uarg = 0;
}
/* ------------------------------------------------------------ */
/* Return the height of the current window */
int
DWindHeight()
{
return(cwin->bot - cwin->top + 1);
}
/* ------------------------------------------------------------ */
/* Switch to one window mode. */
void
DWindOne()
{
struct window *wptr;
if (num_windows <= 1) return;
wptr = (cwin == &windows[0]) ? &windows[1] : &windows[0];
wptr->visible = FALSE;
BMarkDelete(wptr->sstart);
BMarkDelete(wptr->send);
BMarkDelete(wptr->point);
D_ClearWind(wptr);
D_Clear(divide);
num_windows = 1;
cwin->top = 0;
cwin->bot = TMaxRow() - 2;
DScreenRange();
}
/* ------------------------------------------------------------ */
/* Switch which window we are in. */
void
DWindSwap()
{
if (num_windows <= 1) return;
BMarkToPoint(cwin->point);
cwin = (cwin == &windows[0]) ? &windows[1] : &windows[0];
BPointToMark(cwin->sstart);
BMarkToPoint(cwin->send);
BPointToMark(cwin->point);
cwin->isend = FALSE;
DScreenRange();
}
/* ------------------------------------------------------------ */
/* Toggle between one and two window mode. */
void
DWindTog()
{
if (num_windows == 1)
DWindTwo();
else DWindOne();
}
/* ------------------------------------------------------------ */
/* Switch to two window mode. */
void
DWindTwo()
{
struct window *wptr;
if (num_windows > 1) return;
wptr = (cwin == &windows[0]) ? &windows[1] : &windows[0];
wptr->visible = TRUE;
divide = (TMaxRow() - 2) / 2;
cwin->top = 0;
cwin->bot = divide - 1;
wptr->top = divide + 1;
wptr->bot = TMaxRow() - 2;
wptr->offset = cwin->offset;
D_ClearWind(wptr);
wptr->point = BMarkCreate();
BMarkSwap(cwin->sstart);
wptr->sstart = BMarkCreate();
wptr->send = BMarkCreate();
wptr->isend = FALSE;
BMarkSwap(cwin->sstart);
num_windows = 2;
DScreenRange();
}
/* ------------------------------------------------------------ */
/* Switch to two window mode, but go to the other window. */
void
DWindTwoO()
{
DWindTwo();
DWindSwap();
}
/* ------------------------------------------------------------ */
/* Clear the row. */
void
D_Clear(row)
int row;
{
BMarkSetMod(BMarkScreen(row));
screen_line_len[row] = 0;
screen_line_used[row] = TMaxCol() + 1;
}
/* ------------------------------------------------------------ */
/* Clear the screen. */
void
D_ClearScreen()
{
int cnt;
for (cnt = 0; cnt < TMaxRow() - 1; cnt++) {
D_Clear(cnt);
}
}
/* ------------------------------------------------------------ */
/* Clear the window. */
void
D_ClearWind(wptr)
struct window *wptr;
{
int cnt;
for (cnt = wptr->top; cnt <= wptr->bot; cnt++) {
D_Clear(cnt);
}
}
/* ------------------------------------------------------------ */
/* Actually update the display from the buffer */
void
D_IncrDisplay(nested_call)
FLAG nested_call;
{
struct window *wptr;
int cnt;
FLAG ischanged = FALSE;
cnt = BGetCol();
while (cnt < cwin->offset) {
cwin->offset -= TMaxCol() - HOVERLAP;
if (cwin->offset < 0) cwin->offset = 0;
ischanged = TRUE;
}
while (cnt >= cwin->offset + TMaxCol()) {
cwin->offset += TMaxCol() - HOVERLAP;
ischanged = TRUE;
}
if (ischanged) D_ClearWind(cwin);
BPushState();
if (BMarkBuf(cwin->sstart) != cbuf || BIsBeforeMark(cwin->sstart) ||
(cwin->isend && BMarkBuf(cwin->send) == cbuf &&
!BIsBeforeMark(cwin->send))) {
D_ScreenRange(nested_call);
}
BMarkToPoint(cwin->point);
BPointToMark(cwin->sstart);
cwin->isend = FALSE;
point_row = D_InnerDisplay(cwin, cwin->point);
if (BIsBeforeMark(cwin->point) && KIsKey() != 'Y') {
D_IncrDisplay2(nested_call);
}
else {
if (num_windows > 1) {
wptr = (cwin == &windows[0]) ? &windows[1] :
&windows[0];
BPointToMark(wptr->sstart);
D_InnerDisplay(wptr, NULL);
}
D_IncrDisplay3();
}
}
/* ------------------------------------------------------------ */
/* Inner part of IncrDisplay. */
void
D_IncrDisplay2(nested_call)
FLAG nested_call;
{
BPointToMark(cwin->point);
D_ScreenRange(nested_call);
BPopState();
D_IncrDisplay(TRUE);
}
/* ------------------------------------------------------------ */
/* Inner part of IncrDisplay. */
void
D_IncrDisplay3()
{
int col;
BPointToMark(cwin->point);
BPopState();
DModeFlags();
col = BGetCol() - cwin->offset;
if (col < 0) col = 0;
if (col >= TMaxCol()) col = TMaxCol() - 1;
TSetPoint(point_row, col);
}
/* ------------------------------------------------------------ */
/* Display one window. */
int
D_InnerDisplay(wptr, point)
struct window *wptr;
struct mark *point;
{
struct mark *mptr;
int row;
FLAG need_pnt = TRUE;
#if defined(MSDOS)
if (c.g.special == 'J') JDisStart();
#endif
for (row = wptr->top; row <= wptr->bot && KIsKey() != 'Y'; ++row) {
mptr = BMarkScreen(row);
if (BMarkBuf(mptr) != cbuf || BMarkIsMod(mptr) ||
!BIsAtMark(mptr)) {
BMarkToPoint(mptr);
D_InnerDisplay2(wptr, row);
}
else BPointToMark(BMarkScreen(row + 1));
if (point != NULL && need_pnt && BMarkBuf(point) == cbuf &&
BIsAfterMark(point)) {
point_row = row;
need_pnt = FALSE;
}
}
mptr = BMarkScreen(row);
if (BMarkBuf(mptr) != cbuf || !BIsAtMark(mptr)) BMarkSetMod(mptr);
BMarkToPoint(mptr);
if (point != NULL) {
if (KIsKey() != 'Y') {
wptr->isend = TRUE;
BMarkToPoint(wptr->send);
}
if (need_pnt) point_row = wptr->bot + 1;
}
#if defined(MSDOS)
if (c.g.special == 'J') JDisEnd();
#endif
return(point_row);
}
/* ------------------------------------------------------------ */
/* Inner loop of InnerDisplay. */
void
D_InnerDisplay2(wptr, row)
struct window *wptr;
int row;
{
int maxcol = TMaxCol();
int maxoff = maxcol + wptr->offset;
int col;
int chr;
char *srptr;
char *cptr;
int *sllptr;
int *sluptr;
srptr = screen[row];
sllptr = &screen_line_len[row];
sluptr = &screen_line_used[row];
cptr = srptr;
col = 0;
while (cptr - srptr < *sllptr && !BIsEnd() &&
(chr = BGetChar()) != NL && chr != SNL) {
if (col >= wptr->offset) {
if (chr != *cptr) break;
*cptr++;
}
if (chr >= SP && chr <= '~')
col += 1;
else col += TGetWidth(chr, col);
BMoveBy(1);
}
TSetPoint(row, col > wptr->offset ? col - wptr->offset : 0);
TSetOffset(wptr->offset);
if (*sluptr <= maxcol) TAdjCol();
while (!BIsEnd() && (chr = BGetChar()) != NL && chr != SNL &&
col < maxoff) {
if (col >= wptr->offset) *cptr++ = chr;
TPutChar(chr);
if (chr >= SP && chr <= '~')
col += 1;
else col += TGetWidth(chr, col);
BMoveBy(1);
}
if (c.g.vis_gray && !BIsEnd() && BGetChar() == NL && col < maxoff) {
if (col >= wptr->offset) *cptr++ = VIS_NL_CHAR;
TPutChar(VIS_NL_CHAR);
col += TGetWidth(VIS_NL_CHAR, col);
}
TSetOffset(0);
col -= wptr->offset;
if (col < 0) col = 0;
if (col > maxcol) col = maxcol;
TSetPoint(row, col);
if (col < *sluptr || *sllptr > cptr - srptr) TCLEOL();
*sllptr = cptr - srptr;
*sluptr = col;
if (TGetCol() < maxcol) {
if (BIsEnd())
BInvalid();
else if (!IsNL())
SearchNLF();
else BMoveBy(1);
}
else {
if (!IsNL())
SearchNLF();
else BMoveBy(1);
}
}
/* ------------------------------------------------------------ */
/* Do the work for centering the display. */
void
D_ScreenRange(nested_call)
FLAG nested_call;
{
int cnt;
int pref = DPrefLine();
need_screen_range = FALSE;
cwin->isend = FALSE;
BMarkToPoint(cwin->point);
if (nested_call) {
for (cnt = 0; cnt < pref + 1 && SearchNLB(); ++cnt) ;
}
else {
for (cnt = 0; cnt < pref; ++cnt) SearchNLB();
}
CLineA();
BMarkToPoint(cwin->sstart);
BPointToMark(cwin->point);
}
/* end of DISPLAY.C -- Redisplay and Display Routines */